﻿using System.Collections.Generic;
using Lidgren.Network;
using The_World_Server;
using System.Net;
using Server.PC;
using Server.Global;

namespace Server.Network
{
    class NetworkManager
    {
        // private constructor
        private NetworkManager() { }

        // singleton accessor
        static NetworkManager instance;
        public static NetworkManager Instance
        {
            get
            {
                if (instance == null)
                    instance = new NetworkManager();
                return instance;
            }
        }

        public NetServer s_Server;
        public List<NetConnection> connectedClients = new List<NetConnection>(Constants.MAX_PLAYERS - 1);	// List of Client Connections

        public void InitServer()
        {

            // Set Up Players //
            for (int LoopI = 0; LoopI <= Constants.MAX_PLAYERS - 1; LoopI++)
            {
                connectedClients.Add(null);
                Player.Instance.Players.Add(null);
            }

            IPAddress ip = IPAddress.Parse("127.0.0.1");
            NetPeerConfiguration config = new NetPeerConfiguration("Crzy Mirage");
            //config.LocalAddress = ip;
            config.MaximumConnections = 100;
            config.Port = 6265;
            config.ConnectionTimeout = 5;
            config.EnableMessageType(NetIncomingMessageType.DiscoveryRequest);
            s_Server = new NetServer(config);
            s_Server.Start();
        }

        public void ReceivedData()
        {
            NetIncomingMessage im;
            while ((im = s_Server.ReadMessage()) != null)
            {
                // Get incoming index
                int index = connectedClients.IndexOf(im.SenderConnection);

                // handle incoming message
                switch (im.MessageType)
                {
                    case NetIncomingMessageType.DiscoveryRequest:
                        s_Server.SendDiscoveryResponse(null, im.SenderEndPoint);
                        Program.server.TextAdd("Discovery Response Sent to: " + im.SenderEndPoint);
                        break;
                    case NetIncomingMessageType.DebugMessage:
                    case NetIncomingMessageType.ErrorMessage:
                    case NetIncomingMessageType.WarningMessage:
                    case NetIncomingMessageType.VerboseDebugMessage:
                        string text = im.ReadString();
                        Program.server.TextAdd(text);
                        break;
                    case NetIncomingMessageType.StatusChanged:
                        NetConnectionStatus status = (NetConnectionStatus)im.ReadByte();
                        string reason = im.ReadString();
                        if (status == NetConnectionStatus.Connected)
                        {
                            // New Player Connected //
                            connectedClients[connectedClients.IndexOf(null, 0)] = (im.SenderConnection);
                            index = connectedClients.IndexOf(im.SenderConnection);
                            Program.server.TextAdd(NetUtility.ToHexString(im.SenderConnection.RemoteUniqueIdentifier) + " connected!");
                        }
                        if (status == NetConnectionStatus.Disconnected)
                        {
                            if (index < 0)
                            {
                                return;
                            }
                            Player.Instance.LeftGame(index);
                            connectedClients[index] = null;
                            Player.Instance.ClearPlayer(index);
                        }
                        break;
                    case NetIncomingMessageType.Data:
                        HandleTCP.Instance.HandleData(index, im);
                        break;
                    default:
                        Program.server.TextAdd("Unhandled type: " + im.MessageType + " " + im.LengthBytes + " bytes " + im.DeliveryMethod + "|" + im.SequenceChannel);
                        break;
                }
                NetworkManager.Instance.s_Server.Recycle(im);
            }
        }

        private void UpdateConnectionsList()
        {
            //Program.server.lstPlayers.Items.Clear();

            //foreach (NetConnection conn in s_Server.Connections)
            //{
            //    string str = NetUtility.ToHexString(conn.RemoteUniqueIdentifier) + " from " + conn.RemoteEndPoint.ToString() + " [" + conn.Status + "]";
            //    Program.server.lstPlayers.Items.Add(str);
            //}
        }
    }
}
